package com.yzy.fly.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yzy.fly.kernel.model.ability.role.Role;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.*;

import java.time.Duration;

/**
 *
 */
@Configuration
//@ConditionalOnMissingClass({RedisTemplate.class})
//@ConditionalOnMissingBean({RedisConfig.class})
//@AutoConfigureBefore(MyConfiguration.class)
public class AutoRedisConfig {
    private static final Logger logger = LoggerFactory.getLogger(AutoRedisConfig.class);

    @Bean(name = "redisTemplate")
    @ConditionalOnMissingBean({RedisTemplate.class})
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        ////参照StringRedisTemplate内部实现指定序列化器
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setKeySerializer(keySerializer());
        redisTemplate.setHashKeySerializer(keySerializer());
        redisTemplate.setValueSerializer(valueSerializer());
        redisTemplate.setHashValueSerializer(valueSerializer());
        return redisTemplate;
    }

    @Bean(name = "stringRedisTemplate")
    @ConditionalOnMissingBean({StringRedisTemplate.class})
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
        StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
        ////参照StringRedisTemplate内部实现指定序列化器
        stringRedisTemplate.setConnectionFactory(redisConnectionFactory);
        stringRedisTemplate.setKeySerializer(keySerializer());
        stringRedisTemplate.setHashKeySerializer(keySerializer());
        stringRedisTemplate.setValueSerializer(keySerializer());
        stringRedisTemplate.setHashValueSerializer(keySerializer());
        stringRedisTemplate.setDefaultSerializer(keySerializer());
        return stringRedisTemplate;
    }

    private RedisSerializer<String> keySerializer() {
        return new StringRedisSerializer();
    }

    //使用Jackson序列化器
    private RedisSerializer<Object> valueSerializer() {
        return new GenericJackson2JsonRedisSerializer();
    }


    @Bean(name = "roleRedisTemplate")
//@ConditionalOnMissingBean({RedisTemplate.class})
    public <T extends Role> RedisTemplate<String,T> roleRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, T> redisTemplate = new RedisTemplate<>();
        ////参照StringRedisTemplate内部实现指定序列化器
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setKeySerializer(keySerializer());
        redisTemplate.setHashKeySerializer(keySerializer());
        redisTemplate.setValueSerializer(valueSerializer());
        redisTemplate.setHashValueSerializer(valueSerializer());
        return redisTemplate;
    }

//    @Bean
//    public RedisCacheManager empCacheManager(RedisTemplate<Object, FormulaParamInfo>  formulaRedisTemplate) {
//        RedisCacheManager cacheManager = new RedisCacheManager(formulaRedisTemplate);
//        cacheManager.setUsePrefix(true);
//        cacheManager.setDefaultExpiration(60);
//        Map<String,Long> map=new HashMap<String,Long>();
//        map.put("emp",36000L);
//        cacheManager.setExpires(map);
//        return cacheManager;
//    }

//    @Bean
//    public RedisTemplate<Object, Environment> dPageProRedisTemplate(
//            RedisConnectionFactory redisConnectionFactory) {
//        RedisTemplate<Object, Environment> template = new RedisTemplate<>();
//        template.setConnectionFactory(redisConnectionFactory);
//        // 转换 格式
////        Jackson2JsonRedisSerializer<DPagePro> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(DPagePro.class);
////        ObjectMapper om = new ObjectMapper();
////        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
//////        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
////        jackson2JsonRedisSerializer.setObjectMapper(om);
//
//        GsonRedisSerializer<Environment> gsonRedisSerializer = new GsonRedisSerializer<>(Environment.class);
////        template.setDefaultSerializer(jackson2JsonRedisSerializer);
////        template.setKeySerializer(new StringRedisSerializer());
////        template.setHashKeySerializer(new StringRedisSerializer());
//
//        // 设置redis的String/Value的默认序列化方式
//        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
//        template.setKeySerializer(stringRedisSerializer);
//        template.setValueSerializer(gsonRedisSerializer);
//        template.setHashKeySerializer(stringRedisSerializer);
//        template.setHashValueSerializer(gsonRedisSerializer);
//        template.afterPropertiesSet();
//        return template;
//    }

    @Bean
    @ConditionalOnMissingBean
    public RedisCacheManager cacheManager(RedisConnectionFactory factory) {

        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);

        //解决查询缓存转换异常的问题
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        //配置序列化(解决乱码的问题)
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ZERO)
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
                .disableCachingNullValues();

        RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
                .cacheDefaults(config)
                .build();
        return cacheManager;
    }

}